package com.nulldev.util.networking.async2.tcp.client.packets;

import java.util.concurrent.RejectedExecutionException;

import com.nulldev.util.networking.async2.events.ManualResetEvent;
import com.nulldev.util.networking.async2.tcp.client.connectors.TCPConnector;

public final class MessageCollectorTCPClientPacket implements Runnable {

	public ManualResetEvent fDone = new ManualResetEvent(false);
	private final TCPConnector fConnector;
	private final byte[] fData;
	private MessageCollectorTCPClientPacket fPreviousPacket;
	public boolean fCancel = false;

	/**
	 * Constructs a new (incoming) message collector packet.
	 *
	 * Use this class to receive data from the server. This is an incoming message
	 * that will remain in the servers thread pool as a job for the thread pool
	 * workers.
	 *
	 * @param connector      is the packets TCP Connector.
	 * @param data           is the byte[] received.
	 * @param previousPacket is the previous message collector packet of the TCP
	 *                       Connector.
	 */
	public MessageCollectorTCPClientPacket(TCPConnector connector, byte[] data, MessageCollectorTCPClientPacket previousPacket) {
		fConnector = connector;
		fData = data;
		fPreviousPacket = previousPacket;

		sendToThreadPool();
	}

	protected void sendToThreadPool() {
		try {
			fConnector.fMyTCPClient.fMyThreadPool.execute(this);
		} catch (RejectedExecutionException ex) {
			fConnector.forceStop();
		}
	}

	/**
	 * Cancel this message collector packet.
	 *
	 * By calling this method this and all the previous message collector packets
	 * that are stored in the thread pool will be canceled. Call this method for the
	 * last message collector packet of the connector when the connector
	 * disconnects.
	 *
	 */
	public void cancel() {
		fCancel = true;
		fDone.set();
	}

	@Override
	public void run() {
		try {
			if (fPreviousPacket == null) {
				fConnector.fMessageCollector.appendData(fData);
			} else {
				fPreviousPacket.fDone.waitOne();
				if (!fCancel && !fPreviousPacket.fCancel) {
					fConnector.fMessageCollector.appendData(fData);
				} else {
					fCancel = true;
				}

				fPreviousPacket = null;
			}
		} catch (Exception ex) {
		}

		fDone.set();
	}

	/**
	 * Returns the data of this packet.
	 *
	 * @return the data of this packet.
	 */
	public byte[] getData() {
		return fData;
	}
}